package net.lastcoder.ifserver.web;

import net.lastcoder.ifserver.Constants;
import net.lastcoder.ifserver.Globals;
import net.lastcoder.ifserver.Server;
import net.lastcoder.ifserver.module.ModuleManager;
import net.lastcoder.ifserver.module.ModuleNames;
import net.lastcoder.ifserver.nio.Connection;
import net.lastcoder.ifserver.packet.Packet;
import net.lastcoder.ifserver.route.PacketRouter;
import net.lastcoder.ifserver.session.ClientSession;
import net.lastcoder.ifserver.session.SessionHandler;

import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;

/**
 * auth: WenYF
 * date: 2017/3/13
 */
@WebSocket(maxTextMessageSize = 64 * 1024)
public class ClientWebHandler {
    private static final Logger Log = LoggerFactory.getLogger(ClientWebHandler.class);

    private FastJsonParser fastJsonParser = new FastJsonParser();
    private HashMap<Session, WebConnection> webConnectionMaps;
    private PacketRouter packetRouter;
    private SessionHandler sessionHandler;

    public ClientWebHandler() {
        Log.debug("ClientWebHandler construct");
        this.packetRouter = Server.getInstance().getPacketRouter();
        sessionHandler = (SessionHandler) ModuleManager.getInstance()
                .getModule(ModuleNames.SessionHandler);
        webConnectionMaps = new HashMap<>();
    }

    private int getMaxIdleTime() {
        return Globals.getXMLProperty("client.session.idle.time", 6 * 60 * 1000) / 1000;
    }

    private WebConnection createWebConnection(Session session) {
        return new WebConnection(session);
    }

    @OnWebSocketClose
    public void onClose(Session session, int statusCode, String reason) {
        Log.debug("Closing web connection, statusCode = " + statusCode + " reason = " + reason);
        final Connection connection = webConnectionMaps.get(session);;
        if (connection != null) {
            connection.close();
        }
        webConnectionMaps.remove(session);
    }

    @OnWebSocketError
    public void onError(Session session, Throwable t) {
        Log.error("Closing web connection due to error in session: ", t);
        webConnectionMaps.remove(session);
    }

    @OnWebSocketConnect
    public void onConnect(Session session) {
        Log.debug("onConnect session = " + session);
        final WebConnection connection = createWebConnection(session);
//        final int idleTime = getMaxIdleTime() / 2;
//        if (idleTime > 0) {
//            session.setIdleTimeout(idleTime);
//        }

        webConnectionMaps.put(session, connection);
    }

    @OnWebSocketMessage
    public void onMessage(Session session, String message) {
        Log.debug("onMessage session = " + session);
        Log.debug("onMessage message = " + message);
        fastJsonParser.read(message);
        Packet packet = null;
        while (fastJsonParser.hasPacket()) {
            packet = fastJsonParser.getPacket();
            //System.out.println("Received : " + packet.toString());
            Log.debug("Received : " + packet.toString());
            // 这里解析包
            if (packet.getToAddress() == null) {
                packet.setToAddress(Server.getInstance().getServerId());
            }

            WebConnection webConnection = null;
            if (packet.getPacketType() == Constants.PACKET_TYPE_ZERO) {
                // 收到一个为0的包

            } else if (packet.getPacketType() == Constants.PACKET_TYPE_SESSION_OPEN
                    || packet.getPacketType() == Constants.PACKET_TYPE_SESSION_CLOSE) {
                // 递交处理
                try {
                    webConnection = webConnectionMaps.get(session);
                    sessionHandler.handle(webConnection, packet);
                } catch (Exception e) {
                    // TODO
                    Log.error(e.getMessage(), e);
                    if (webConnection != null) {
                        webConnection.close();
                    }
                }
            } else {
                webConnection = webConnectionMaps.get(session);
                if (webConnection != null) {
                    ClientSession clientSession = (ClientSession) webConnection.getOwner();
                    if (clientSession != null) {
                        clientSession.incrementClientPacketCount();
                    }
                    packetRouter.route(clientSession, packet, true);
                }
            }
        }
    }
}
